﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using InformationSystem.BLL.Core.Model;
using Spring.Data.Common;
using Spring.Data.Generic;
using System.Data;
using InformationSystem.Framework.Dao;

namespace InformationSystem.BLL.Core.Dao.Impl
{
    public class ForumDaoImpl : InfoSysAdoDaoSupport, IForumDao
    {
        internal class ThreadTypeRow<T> : IRowMapper<T> where T : ThreadType, new()
        {
            public T MapRow(IDataReader reader, int rowNum)
            {
                T threadType = new T();

                threadType.AutoID = reader.GetInt32(reader.GetOrdinal("autoid"));
                threadType.CollegeID = reader.GetInt32(reader.GetOrdinal("collegeid"));
                threadType.TypeID = reader.GetInt32(reader.GetOrdinal("typeid"));
                threadType.TypeName = reader.GetString(reader.GetOrdinal("typename"));
                return threadType;
            }
        }

        internal class ThreadReplyRow<T> : IRowMapper<T> where T : ThreadReplyInfo, new()
        {
            public T MapRow(IDataReader reader, int rowNum)
            {
                T threadreply = new T();
                threadreply.ForumReplyID = reader.GetInt32(reader.GetOrdinal("autoid"));
                threadreply.ThreadID = reader.GetInt32(reader.GetOrdinal("threadid"));
                threadreply.ReplyUserID = reader.GetString(reader.GetOrdinal("replyuserid"));
                threadreply.ReplyUserName = reader.GetString(reader.GetOrdinal("replyusername"));
                threadreply.Content = reader.GetString(reader.GetOrdinal("content"));
                threadreply.ReplyTime = reader.GetDateTime(reader.GetOrdinal("replytime"));
                threadreply.HideName = reader.GetBoolean(reader.GetOrdinal("hidename"));
                threadreply.IsDeletedByAdmin = reader.GetBoolean(reader.GetOrdinal("isdeletedbyadmin"));

                return threadreply;
            }
        }

        internal class ThreadRow<T> : IRowMapper<T> where T : ThreadInfo, new()
        {
            public T MapRow(IDataReader reader, int rownum)
            {
                T threadinfo = new T();
                threadinfo.ThreadID = reader.GetInt32(reader.GetOrdinal("threadid"));
                threadinfo.CollegeID = reader.GetInt32(reader.GetOrdinal("collegeid"));
                threadinfo.ThreadType = reader.GetInt32(reader.GetOrdinal("threadtype"));
                threadinfo.ThreadTypeName = reader.GetString(reader.GetOrdinal("typename"));
                threadinfo.ThreadSubject = reader.GetString(reader.GetOrdinal("threadsubject"));
                threadinfo.Content = reader.GetString(reader.GetOrdinal("content"));
                threadinfo.CreatUserID = reader.GetString(reader.GetOrdinal("createuserid"));
                threadinfo.CreatUserName = reader.GetString(reader.GetOrdinal("createusername"));
                threadinfo.HideName = reader.GetBoolean(reader.GetOrdinal("hidename"));
                threadinfo.CanReplyHideName = reader.GetBoolean(reader.GetOrdinal("canreplyhidename"));
                threadinfo.IsApproved = reader.GetBoolean(reader.GetOrdinal("isapproved"));
                threadinfo.CheckUserID = reader.GetString(reader.GetOrdinal("checkuserid"));
                threadinfo.CheckUserName = reader.GetString(reader.GetOrdinal("checkusername"));
                threadinfo.CreateTime = reader.GetDateTime(reader.GetOrdinal("createtime"));
                threadinfo.CheckTime = reader.GetDateTime(reader.GetOrdinal("checktime"));
                threadinfo.ReplyCount = reader.GetInt32(reader.GetOrdinal("replycount"));
                threadinfo.VisitedCount = reader.GetInt32(reader.GetOrdinal("visitedcount"));
                threadinfo.LastReplyTime = reader.GetDateTime(reader.GetOrdinal("lastreplytime"));
                threadinfo.LastReplyUserID = reader.GetString(reader.GetOrdinal("lastreplyuserid"));
                threadinfo.LastReplyUserName = reader.GetString(reader.GetOrdinal("lastreplyusername"));
                threadinfo.LastReplyHideName = reader.GetBoolean(reader.GetOrdinal("lastreplyhidename"));
                threadinfo.IsOnTop = reader.GetBoolean(reader.GetOrdinal("isontop"));
                threadinfo.CanReply = reader.GetBoolean(reader.GetOrdinal("canreply"));
                return threadinfo;
            }
        }

        public IList<ThreadType> GetForumTypeList(int collegeID)
        {
            string selectSql = @"select autoid,collegeid,typeid,typename
                                    from ThreadType
                                    where collegeid=@collegeid";
            IDbParametersBuilder builder = CreateDbParametersBuilder();
            builder.Create().Name("collegeid").Type(DbType.Int32).Value(collegeID);
            return AdoTemplate.QueryWithRowMapper<ThreadType>(CommandType.Text, selectSql, new ThreadTypeRow<ThreadType>(), builder.GetParameters());
        }


        public bool CreateThread(ThreadInfo tinfo)
        {
            string insertSql = @"insert into Forum
	                                (threadid,collegeid,threadtype,threadsubject,[content],
	                                createuserid,createusername,hidename,canreplyhidename,
	                                isapproved ,checkuserid,checkusername,createtime,
	                                checktime,replycount,visitedcount,lastreplytime,
	                                lastreplyuserid,lastreplyusername,lastreplyhidename,isontop,canreply) 
                                values (@threadid,@collegeid,@threadtype,@threadsubject,@content,
	                                @createuserid,@createusername,@hidename,@canreplyhidename,
	                                @isapproved,@checkuserid,@checkusername,@createtime,
	                                @checktime,@replycount,@visitedcount,@lastreplytime,
	                                @lastreplyuserid,@lastreplyusername,@lastreplyhidename,@isontop,@canreply)";
            IDbParametersBuilder builder = null;

            int useableid = base.GetUseableID("Forum", "threadid");
            builder = CreateDbParametersBuilder();
            builder.Create().Name("threadid").Type(DbType.Int32).Value(useableid);
            builder.Create().Name("collegeid").Type(DbType.Int32).Value(tinfo.CollegeID);
            builder.Create().Name("threadtype").Type(DbType.Int32).Value(tinfo.ThreadType);
            builder.Create().Name("threadsubject").Type(DbType.String).Value(tinfo.ThreadSubject);
            builder.Create().Name("content").Type(DbType.String).Value(tinfo.Content);
            builder.Create().Name("createuserid").Type(DbType.String).Value(tinfo.CreatUserID);
            builder.Create().Name("createusername").Type(DbType.String).Value(tinfo.CreatUserName);
            builder.Create().Name("hidename").Type(DbType.Boolean).Value(tinfo.HideName);
            builder.Create().Name("canreplyhidename").Type(DbType.Boolean).Value(tinfo.CanReplyHideName);
            builder.Create().Name("isapproved").Type(DbType.Boolean).Value(tinfo.IsApproved);
            builder.Create().Name("checkuserid").Type(DbType.String).Value(tinfo.CheckUserID);
            builder.Create().Name("checkusername").Type(DbType.String).Value(tinfo.CheckUserName);
            builder.Create().Name("createtime").Type(DbType.DateTime).Value(tinfo.CreateTime);
            builder.Create().Name("checktime").Type(DbType.DateTime).Value(tinfo.CheckTime);
            builder.Create().Name("replycount").Type(DbType.Int32).Value(tinfo.ReplyCount);
            builder.Create().Name("visitedcount").Type(DbType.Int32).Value(tinfo.VisitedCount);
            builder.Create().Name("lastreplytime").Type(DbType.DateTime).Value(tinfo.LastReplyTime);
            builder.Create().Name("lastreplyuserid").Type(DbType.String).Value(tinfo.LastReplyUserID);
            builder.Create().Name("lastreplyusername").Type(DbType.String).Value(tinfo.LastReplyUserName);
            builder.Create().Name("lastreplyhidename").Type(DbType.Boolean).Value(tinfo.LastReplyHideName);
            builder.Create().Name("isontop").Type(DbType.Boolean).Value(tinfo.IsOnTop);
            builder.Create().Name("canreply").Type(DbType.Boolean).Value(tinfo.CanReply);

            AdoTemplate.ExecuteNonQuery(CommandType.Text, insertSql, builder.GetParameters());
            tinfo.ThreadID = useableid;
            return true;
        }


        public IList<ThreadInfo> GetThreads(int collegeid, int threadtype, int pagesize, int requestpage, out int totalrecordcount)
        {

            totalrecordcount = 0;
            IDbParameters parameters = CreateDbParameters();
            parameters.Add("collegeid", DbType.Int32).Value = collegeid;
            parameters.Add("threadtype", DbType.Int32).Value = threadtype;
            parameters.Add("pagesize", DbType.Int32).Value = pagesize;
            parameters.Add("currentpage", DbType.Int32).Value = requestpage;
            parameters.AddOut("totalrecords", DbType.Int32).Value = totalrecordcount;
            IList<ThreadInfo> result = AdoTemplate.QueryWithRowMapper<ThreadInfo>(CommandType.StoredProcedure, "uspGetthreadpage", new ThreadRow<ThreadInfo>(), parameters);
            totalrecordcount = (int)parameters["@totalrecords"].Value;
            return result;
        }

        public bool DeleteThread(int threadid)
        {
            string deleteSql = "delete from Forum where threadid=@threadid;delete from ForumReply where threadid=@threadid";
            IDbParametersBuilder builder = CreateDbParametersBuilder();
            builder.Create().Name("threadid").Type(DbType.Int32).Value(threadid);
            AdoTemplate.ExecuteNonQuery(CommandType.Text, deleteSql, builder.GetParameters());
            return true;
        }

        public bool DeleteReply(int replyid)
        {
            string deleteSql = "delete from ForumReply where autoid=@autoid";
            IDbParametersBuilder builder = CreateDbParametersBuilder();
            builder.Create().Name("autoid").Type(DbType.Int32).Value(replyid);
            return AdoTemplate.ExecuteNonQuery(CommandType.Text, deleteSql, builder.GetParameters()) == 1;
        }

        public bool HiLightThread(int replyid, bool hilight)
        {
            throw new NotImplementedException();
        }

        public bool CreateReply(int threadid, ThreadReplyInfo rinfo)
        {
            string insertSql = @"insert into ForumReply
	                                (threadid,replyuserid,replyusername,[content],
	                                replytime,hidename,isdeletedbyadmin) 
                                values (@threadid,@replyuserid,@replyusername,@content,
	                                @replytime,@hidename,@isdeletedbyadmin)";
            IDbParametersBuilder builder = CreateDbParametersBuilder();
            builder.Create().Name("threadid").Type(DbType.Int32).Value(threadid);
            builder.Create().Name("replyuserid").Type(DbType.String).Value(rinfo.ReplyUserID);
            builder.Create().Name("replyusername").Type(DbType.String).Value(rinfo.ReplyUserName);
            builder.Create().Name("content").Type(DbType.String).Value(rinfo.Content);
            builder.Create().Name("replytime").Type(DbType.DateTime).Value(rinfo.ReplyTime);
            builder.Create().Name("hidename").Type(DbType.Boolean).Value(rinfo.HideName);
            builder.Create().Name("isdeletedbyadmin").Type(DbType.Boolean).Value(rinfo.IsDeletedByAdmin);

            AdoTemplate.ExecuteNonQuery(CommandType.Text, insertSql, builder.GetParameters());
            return true;
        }

        public ThreadInfo GetThreadDetail(int threadid)
        {
            string selectSql = @"select 
                                    threadid,Forum.collegeid,threadtype,typename,threadsubject,[content],
	                                createuserid,createusername,hidename,canreplyhidename,
	                                isapproved ,checkuserid,checkusername,createtime,
	                                checktime,replycount,visitedcount,lastreplytime,
	                                lastreplyuserid,lastreplyusername,lastreplyhidename,isontop,canreply
                                from 
                                    Forum 
                                 left join ThreadType on  Forum.collegeid=ThreadType.collegeid and threadtype=typeid
                                where threadid=@threadid";
            IDbParametersBuilder builder = CreateDbParametersBuilder();
            builder.Create().Name("threadid").Type(DbType.Int32).Value(threadid);
            try
            {
                return AdoTemplate.QueryForObject<ThreadInfo>(CommandType.Text, selectSql, new ThreadRow<ThreadInfo>(), builder.GetParameters());
            }
            catch (Exception)
            {
                return null;
            }

        }

        public bool UpdateReadCount(int threadid)
        {
            string updateSql = "update Forum set visitedcount=visitedcount+1 where threadid=@threadid";
            IDbParametersBuilder builder = CreateDbParametersBuilder();
            builder.Create().Name("threadid").Type(DbType.Int32).Value(threadid);
            return AdoTemplate.ExecuteNonQuery(CommandType.Text, updateSql, builder.GetParameters()) == 1;
        }

        public bool UpdateReplyCount(int threadid)
        {
            string updateSql = "update Forum set replycount=(select count(*) from ForumReply where threadid=@threadid) where threadid=@threadid";
            IDbParametersBuilder builder = CreateDbParametersBuilder();
            builder.Create().Name("threadid").Type(DbType.Int32).Value(threadid);
            return AdoTemplate.ExecuteNonQuery(CommandType.Text, updateSql, builder.GetParameters()) == 1;
        }

        public IList<ThreadReplyInfo> GetThreadReplyInfo(int threadid, int pagesize, int requestpage, out int totalrecordcount)
        {
            totalrecordcount = 0;
            IDbParameters parameters = CreateDbParameters();
            parameters.Add("threadid", DbType.Int32).Value = threadid;
            parameters.Add("pagesize", DbType.Int32).Value = pagesize;
            parameters.Add("currentpage", DbType.Int32).Value = requestpage;
            parameters.AddOut("totalrecords", DbType.Int32).Value = totalrecordcount;
            IList<ThreadReplyInfo> result = AdoTemplate.QueryWithRowMapper<ThreadReplyInfo>(CommandType.StoredProcedure, "uspGetthreadreply", new ThreadReplyRow<ThreadReplyInfo>(), parameters);
            totalrecordcount = (int)parameters["@totalrecords"].Value;
            return result;
        }


        public ThreadReplyInfo GetThreadReplyDetail(int replyid)
        {
            string selectSql = @"select autoid,threadid,replyuserid,replyusername,
                                '' as content,replytime,hidename,isdeletedbyadmin 
                                from ForumReply where autoid=@replyid";
            IDbParametersBuilder builder = CreateDbParametersBuilder();
            builder.Create().Name("replyid").Type(DbType.Int32).Value(replyid);
            try
            {
                return AdoTemplate.QueryForObject<ThreadReplyInfo>(CommandType.Text, selectSql, new ThreadReplyRow<ThreadReplyInfo>(), builder.GetParameters());
            }
            catch (Exception)
            {
                return null;
            }
        }


        public int GetThreadReplysCount(int threadid)
        {
            string selectSql = "select count(*) from ForumReply where threadid=@threadid";
            IDbParametersBuilder builder = CreateDbParametersBuilder();
            builder.Create().Name("threadid").Type(DbType.Int32).Value(threadid);

            return (int)AdoTemplate.ExecuteScalar(CommandType.Text, selectSql, builder.GetParameters());
        }


        public bool UpdateThreadLastReplyInfo(int threadid, ThreadReplyInfo rinfo)
        {
            string updateSql = @"update Forum set 
                                    lastreplytime=@lastreplytime,lastreplyuserid=@lastreplyuserid ,
                                    lastreplyusername=@lastreplyusername,lastreplyhidename=@lastreplyhidename
                                where threadid=@threadid";
            IDbParametersBuilder builder = CreateDbParametersBuilder();
            builder.Create().Name("threadid").Type(DbType.Int32).Value(threadid);
            builder.Create().Name("lastreplytime").Type(DbType.DateTime).Value(rinfo.ReplyTime);
            builder.Create().Name("lastreplyuserid").Type(DbType.String).Value(rinfo.ReplyUserID);
            builder.Create().Name("lastreplyusername").Type(DbType.String).Value(rinfo.ReplyUserName);
            builder.Create().Name("lastreplyhidename").Type(DbType.Boolean).Value(rinfo.HideName);
            AdoTemplate.ExecuteNonQuery(CommandType.Text, updateSql, builder.GetParameters());
            return true;
        }
    }
}
